
#pragma once
using namespace System;

namespace GRIP
{
	namespace Cuda
	{
		/// <summary>
		/// Internal class for holding an unmanaged pointer to a GPU byte array.
		/// </summary>
		private class InternalCudaDeviceBuffer
		{
		public:
			/// <summary>
			/// Internal class for holding an unmanaged pointer to a GPU byte array.
			/// </summary>
			/// <param name="size">Size of the buffer in bytes</param>
			InternalCudaDeviceBuffer(int size);

			~InternalCudaDeviceBuffer();
			BYTE* buffer;
		};
		
		/// <summary>
		/// CudaDeviceBuffer is a managed wrapper for a GPU byte array.
		/// </summary>
		public ref class CudaDeviceBuffer
		{
		public:
			/// <summary>
			/// CudaDeviceBuffer is a managed wrapper for a GPU byte array.
			/// </summary>
			/// <param name="width">Width of the array</param>
			/// <param name="height">Height of the array</param>
			/// <param name="elementSize">Size of a single element in bytes</param>
			CudaDeviceBuffer(int width, int height, int elementSize);

			/// <summary>
			/// Returns an IntPtr to the data for use with managed code.
			/// </summary>
			/// <returns>IntPtr to the GPU array</returns>
			IntPtr Data();

			/// <summary>
			/// Returns a pointer to the byte array for use with unmanaged code.
			/// </summary>
			/// <returns>Pointer to the GPU array</returns>
			BYTE* Ptr();
			
			/// <summary>
			/// Returns the total size of the buffer in bytes.
			/// </summary>
			/// <returns>Length of the buffer in bytes</returns>
			int BufferSize();
			
			/// <summary>
			/// Returns the width of the buffer.
			/// </summary>
			/// <returns>Width of the buffer</returns>
			int GetWidth();
			
			/// <summary>
			/// Returns the height of the buffer.
			/// </summary>
			/// <returns>Height of the buffer</returns>
			int GetHeight();

			/// <summary>
			/// Clears the buffer.
			/// </summary>
			void ClearData();

		private:
			InternalCudaDeviceBuffer* InternalBuffer;
			IntPtr ManagedBufferPtr;
			int Size;
			int Width;
			int Height;
		};
	}
}